package com.sendi.system.bean;
 
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import javax.sql.DataSource;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.impl.SessionFactoryImpl;

import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.util.ClassUtils;

import com.sendi.system.entity.SysBeanMap;

 
public class AnnotationSessionFactoryBean extends LocalSessionFactoryBean implements ResourceLoaderAware {

	private static final String RESOURCE_PATTERN = "/**/*.class";
 
	 private Class[] annotatedClasses;

	private String[] annotatedPackages;

	private String[] packagesToScan;

	public ArrayList<String>  beanname;
    public ArrayList<SysBeanMap> beanlist;
	private TypeFilter[] entityTypeFilters = new TypeFilter[] {
			new AnnotationTypeFilter(Entity.class, false),
			new AnnotationTypeFilter(Embeddable.class, false),
			new AnnotationTypeFilter(MappedSuperclass.class, false),
			new AnnotationTypeFilter(org.hibernate.annotations.Entity.class, false)};

	private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();


	public AnnotationSessionFactoryBean() {
		setConfigurationClass(AnnotationConfiguration.class);
	 
		
	}

 

	@Override
	public void setConfigurationClass(Class configurationClass) {
		if (configurationClass == null || !AnnotationConfiguration.class.isAssignableFrom(configurationClass)) {
			throw new IllegalArgumentException(
					"AnnotationSessionFactoryBean only supports AnnotationConfiguration or subclasses");
		}
		super.setConfigurationClass(configurationClass);
		
		
	}

 
	public void setAnnotatedClasses(Class[] annotatedClasses) {
	 
 
	  Connection con;
		try {
			beanname=new ArrayList<String>();
			beanlist=new ArrayList<SysBeanMap>();
			con = this.getDataSource().getConnection();
			
			 if(con!=null)
			 {
				  Statement state=con.createStatement();
				  String sql="select * from sys_bean_map";
				 ResultSet rs=state.executeQuery(sql);
				 if(rs!=null)
				 {
					 	while(rs.next())
					 	{
					 		String bn=rs.getString("bean_name");
					 		String tobsname=rs.getString("beam_bsname");
					 		String remark=rs.getString("remark");
					 		String islog=rs.getString("islog");
					 		beanname.add(bn);
					 		beanlist.add(new SysBeanMap(bn,tobsname,remark,islog));
					  	}
				 }
		 		 	ArrayList<Class> anl=new ArrayList<Class>();
				 	for(String a:beanname)
				 	{
				 		try
				 		{
				 			  Class t=Class.forName(a);
				 			  if(t!=null)
				 			  {
				 				  anl.add(t);  
				 			  }
				 			 
						 	//   this.annotatedClasses[i]=t;
					 	}
				 		catch (ClassNotFoundException e) {
							 System.out.println("加载entity bean 出错"+e.getMessage());
						}
				 	 
				   	}
					int i=0;
					int size=anl.size();
					this.annotatedClasses=new Class[size];
					anl.toArray(this.annotatedClasses);
		 	 }
					 
			 
		} catch (SQLException e) {
		 
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		 
				 	
			   
	}
 
	public void setAnnotatedPackages(String[] annotatedPackages) {
		this.annotatedPackages = annotatedPackages;
	}
 
	public void setPackagesToScan(String[] packagesToScan) {
		this.packagesToScan = packagesToScan;
	}

 
	public void setEntityTypeFilters(TypeFilter[] entityTypeFilters) {
		this.entityTypeFilters = entityTypeFilters;
	}

	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
	}


 
	@Override
	protected void postProcessMappings(Configuration config) throws HibernateException {
	  	AnnotationConfiguration annConfig = (AnnotationConfiguration) config;
		if (this.annotatedClasses != null) {
			for (Class annotatedClass : this.annotatedClasses) {
				annConfig.addAnnotatedClass(annotatedClass);
		 	}
		}
 
		//annConfig.buildMappings();
	 	if (this.annotatedPackages != null) {
			for (String annotatedPackage : this.annotatedPackages) {
				annConfig.addPackage(annotatedPackage);
			}
		}
		scanPackages(annConfig);
	}

 
	protected void scanPackages(AnnotationConfiguration config) {
		if (this.packagesToScan != null) {
			try {
				for (String pkg : this.packagesToScan) {
					String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
							ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;
					Resource[] resources = this.resourcePatternResolver.getResources(pattern);
					MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
					for (Resource resource : resources) {
						if (resource.isReadable()) {
							MetadataReader reader = readerFactory.getMetadataReader(resource);
							String className = reader.getClassMetadata().getClassName();
							if (matchesFilter(reader, readerFactory)) {
								config.addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className));
							}
						}
					}
				}
			}
			catch (IOException ex) {
				throw new MappingException("Failed to scan classpath for unlisted classes", ex);
			}
			catch (ClassNotFoundException ex) {
				throw new MappingException("Failed to load annotated classes from classpath", ex);
			}
		}
	}
 
	private boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException {
		if (this.entityTypeFilters != null) {
			for (TypeFilter filter : this.entityTypeFilters) {
				if (filter.match(reader, readerFactory)) {
					return true;
				}
			}
		}
		return false;
	}

 
	@Override
	protected final void postProcessConfiguration(Configuration config) throws HibernateException {
		postProcessAnnotationConfiguration((AnnotationConfiguration) config);
	}

 
	protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {
	}



	public ArrayList<SysBeanMap> getBeanlist() {
		return beanlist;
	}



	public void setBeanlist(ArrayList<SysBeanMap> beanlist) {
		this.beanlist = beanlist;
	}


	 
  

}
